using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using WebSMS.Core.ResponseEntity;

namespace WebSMS;

public class RuleService : ITRules,ITransient
{
    private readonly IRepository<RulePo> _ruleRepository;
    private readonly IRepository<UserRuleLinks> _userRuleLinkRepository;
    private readonly IRepository<UserPo> _userLinkRepository;
    private readonly IRepository<DataPo> _dataLinkRepository;
    private readonly IRepository<RuleDataLinks> _ruleDataLinkRepository;
    private readonly UserRuleLinksService _ruleLinksService;
    private readonly RuleDataLinkService _ruleDataLinkService;
    private readonly IRepository<MenuPo> _menuRepository;
    private readonly IRepository<RuleMenuLinks> _ruleMenuRepository;
    public RuleService(IRepository<RulePo> ruleRepository,
        RuleDataLinkService ruleDataLinkService,
        IRepository<UserPo> userRepo,
        IRepository<RuleDataLinks> ruleDataLinkRepository,
        IRepository<UserRuleLinks> userRuleLinksRepo,
        UserRuleLinksService ruleLinksService,
        IRepository<MenuPo> menuRepo,
        IRepository<RuleMenuLinks> ruleMenuRepo,
            IRepository<DataPo> dataRepo)
    {
        _ruleRepository = ruleRepository;
        _ruleLinksService = ruleLinksService;
        _ruleDataLinkService = ruleDataLinkService;
        _menuRepository = menuRepo;
        _ruleMenuRepository = ruleMenuRepo;
        _userLinkRepository = userRepo;
        _userRuleLinkRepository = userRuleLinksRepo;
        _ruleDataLinkRepository = ruleDataLinkRepository;
        _dataLinkRepository = dataRepo;
    }

    public PagedList<RulePo> GetRulesList(int page, int size)
    {
        if(page <= 0 || size <= 0)
        {
            page = 1;
            size = 10;
        }
        return _ruleRepository.AsQueryable().ToPagedList(page, size);
       /*from rule in _ruleRepository.AsQueryable() 
           join ur _ruleDataLinkService.asQueryable()*/
    }
    public List<RulePo> GetRulesList()
    {
        return _ruleRepository.AsQueryable().ToList();
    }

    public async Task<bool> AddRules(RulePo rule)
    {
        await _ruleRepository.InsertNowAsync(rule);
        return true;
    }

    public async Task<bool> UpdateRules(RulePo rule)
    {
       await _ruleRepository.UpdateNowAsync(rule);
       return true;
    }

    public async Task<bool> DeleteRules(Guid id)
    {
         
         List<UserRuleLinks> userId =  _ruleLinksService.GetUserRuleByUserId(id);
         if (userId.Count != 0)
         {
             return false;
         }
         await _ruleRepository.DeleteNowAsync(id);
         return true;
    }

    public async Task<IQueryable> GetRuleMenuList()
    {
      var queryable =  from rule in _ruleRepository.AsQueryable()
            join link in _ruleMenuRepository.AsQueryable()
                on rule.Id equals link.RuleId into ruleLinks
            from ruleLink in ruleLinks.DefaultIfEmpty()
            join menu in _menuRepository.AsQueryable()
                on ruleLink.MenuId equals menu.Id into menuLinks
            from menuLink in menuLinks.DefaultIfEmpty()
            group menuLink by new
            {
                rule.Id,
                rule.Name,
                rule.Description
            }
            into ruleGroup
            select new RuleMenuResponse()
            {
                Id = ruleGroup.Key.Id,
                Name = ruleGroup.Key.Name,
                Description = ruleGroup.Key.Description,
                MenuList = ruleGroup.Where(menu => menu != null).ToList()
            };
      return queryable;
    }

    
    public async Task<bool> AddRuleMenu(Guid ruleId, Guid menuId)
    {
        await _ruleMenuRepository.InsertNowAsync(new RuleMenuLinks() { Id = Guid.NewGuid(),RuleId = ruleId, MenuId = menuId });
        return true;
    }

    public async Task<bool> DeleteRuleMenu(Guid ruleId)
    {
        var queryable = _ruleMenuRepository.Where(r => r.RuleId == ruleId);
        await _ruleMenuRepository.DeleteNowAsync(queryable);
        return true;
    }

    public async Task<object> GetRuleDetails(Guid ruleId)
    {
        // 查询与规则关联的用户
        var userIds = await _userRuleLinkRepository.AsQueryable()
            .Where(rl => rl.RuleId == ruleId)
            .Select(rl => rl.UserId)
            .ToListAsync();

        var users = _userLinkRepository.AsQueryable()
            .Where(u => userIds.Contains(u.Id)).Select(user => new UserDtoR
            {
                UserId = user.Id,
                Username = user.Username,
                Email = user.Email,
                Phone = user.Phone,
                IsActive = user.IsActive
            }).ToList();

        // 查询与规则关联的数据权限
        var dataTypeIds = await _ruleDataLinkRepository.AsQueryable()
            .Where(rd => rd.RuleId == ruleId)
            .Select(rd => rd.DataTypeId)
            .ToListAsync();

        var dataPermissions = await _dataLinkRepository.AsQueryable()
            .Where(d => dataTypeIds.Contains(d.Id))
            .Select(d => new DataPermissionDto
            {
                DataId = d.Id,
                DataType = d.DataType
            })
            .ToListAsync();

        // 查询与规则关联的菜单权限
        var menuIds = await _ruleMenuRepository.AsQueryable()
            .Where(rm => rm.RuleId == ruleId)
            .Select(rm => rm.MenuId)
            .ToListAsync();

        var menus = await _menuRepository.AsQueryable()
            .Where(m => menuIds.Contains(m.Id.Value))
            .Select(m => new MenuDto
            {
                MenuId = m.Id.Value,
                MenuName = m.Name,
                Path = m.Path,
                Icon = m.Icon,
                ParentMenuId = m.ParentMenu,
                Priority = m.Priority
            })
            .ToListAsync();

        // 组装结果
        var result = new RuleDetailsResponse
        {
            RuleId = ruleId,
            Users = users,
            DataPermissions = dataPermissions,
            Menus = menus
        };

        return result;
    }
}